#include "tcpacceptor.h"
#include <boost/bind.hpp>

TcpAcceptor::TcpAcceptor(Implement &impl) :
    m_acceptor(impl)
{

}

TcpAcceptor::~TcpAcceptor()
{

}

int TcpAcceptor::open(const std::string &host, unsigned short port, int listenCount)
{
    ErrorCode ec;
    Endpoint ep;

    if(m_acceptor.is_open()){
        return boost::system::errc::already_connected;
    }

    if(
            host.empty() ||
            !host.compare("0.0.0.0") ||
            !host.compare("any")
      ){
        ep = Endpoint(boost::asio::ip::tcp::v4(), port);
    }else{
        Address addr = Address::from_string(host, ec);

        if(ec){
            return ec.value();
        }

        ep = Endpoint(addr, port);
    }

    m_acceptor.open(boost::asio::ip::tcp::v4(), ec);

    if(ec){
        return ec.value();
    }

    m_acceptor.set_option(Acceptor::reuse_address(true), ec);

    if(ec){
        return ec.value();
    }

    m_acceptor.bind(ep, ec);

    if(ec){
        return ec.value();
    }

    m_acceptor.listen(listenCount ?  listenCount : Acceptor::max_connections, ec);

    if(ec){
        return ec.value();
    }

    return boost::system::errc::success;
}

void TcpAcceptor::close()
{
    ErrorCode ec;

    m_acceptor.close(ec);
}

void TcpAcceptor::accept(Socket &sock, BOOST_ASIO_MOVE_ARG(Notifier) n)
{
    m_acceptor.async_accept
            (
                sock,
                boost::bind
                (
                    &TcpAcceptor::onAccepted,
                    this,
                    Notifier(n),
                    _1
                )
            );
}

void TcpAcceptor::onAccepted(Notifier n, ErrorCode ec)
{
    n(ec.value());
}
